#ifndef Connection_h__
#define Connection_h__

#include "ConstBufferSequence.h"
#include "RawPackage.h"
#include <boost/asio.hpp>
#include "../Common/Common.h"
#include "../Common/Runable.h"

class ConnectionListener;
class ConnectionClosedListener;

/// Represents a single Connection from a client.
class Connection
	: public boost::enable_shared_from_this<Connection>,
	private boost::noncopyable,
	public Runable
{
public:
	/// Construct a Connection with the given io_service.
	explicit Connection(boost::asio::io_service& io_service, ConnectionClosedListener* closed_listener, 
		ConnectionListener* listener = NULL);

	virtual ~Connection();

	virtual void update(uint32 timeElapse);

	/// Get the socket associated with the Connection.
	boost::asio::ip::tcp::socket& socket();

	/// Start the first asynchronous operation for the Connection.
	bool start();

	/// Stop all asynchronous operations associated with the Connection.
	void stop(bool isNotify = true);

	virtual Connection* span(boost::asio::io_service& io_service, ConnectionClosedListener* listerner)
	{
		return new Connection(io_service,listerner);
	}

	void pushData(ArrayBuffer* buffer);

	void startWrite();

	uint64 getID() const
	{
		return id_;
	}

	void setID(uint64 id)
	{
		id_ = id;
	}

	bool isStopped() const
	{
		return closed_;
	}

	ConnectionListener* getConnectionListener() const
	{
		return m_listener;
	}

	void setConnectionListener(ConnectionListener* l)
	{
		m_listener = l;
	}

protected:
	virtual bool onStart() { return false; }
	virtual bool onStop() { return false; }

	virtual bool onReadRawData(uint8* buffer, size_t s) { return false; }
	virtual bool onPushRawData(const uint8* buffer, size_t s) { return false; }

private:
	/// Handle completion of a read operation.
	void handleRead(const boost::system::error_code& e, std::size_t bytes_transferred);

	/// Handle completion of a write operation.
	void handleWrite(const boost::system::error_code& e);

	/// Socket for the Connection.
	boost::asio::ip::tcp::socket socket_;

	/// Buffer for incoming data.
	boost::array<uint8, 8192> buffer_;

	boost::scoped_ptr<ConstBufferSequence> m_outcoming;
	boost::scoped_ptr<ConstBufferSequence> m_incoming;
	bool writting_;
	volatile bool closed_;

	uint64 id_;
	ConnectionListener* m_listener;
	ConnectionClosedListener* m_closed_listener;
	boost::mutex mutex_;
};

typedef boost::shared_ptr<Connection> ConnectionPtr;

#endif // Connection_h__